Helpfile for formula 0.82 (Freeware) (implention on acorn archimdes) (by MUFTI)
-------------------------------------------------------------------------------

Preface
=======


It's difficult to say exact what formula is:
It generates Macro-assembler code from highlevel-language-like Commands, which 
are enbedded in other Macro-assembler code (Code for the TLA macroassember)

The difference to a compiler, which can inline assemblercode is:
The exchanging of data between formulacommands and the macro-assembler parts
of the inputfile, cause formulacommands can work with (most) Machinecode 
Registers (on archimedes R0-R10).
Unlike common compilers which can inline assemblercode, you don't have to
do complicated dataexchange operations via memory or stack before and after
your assemblerpart.

If it's syntax would be more elegant and there will be more typechecking, 
i would say it is a sort of (the codeproducting part of) a compiler.
If it would optimize the generated Macro-Assembler better, i would say 
it's a "symbolic Assembler". 
If the conversion would be faster, i would say it's a tool for rapid 
prototyping of Macro-assembler programs.
If the following Macroassembler would not have so much to do, i would say its a
tool to support debugging.


Unfortunally the following Macroassembler can't work with floatingpointcommands,
therefore formula can't be used floatingpoint for floatingpoint problems.
 
Formula is useful in every problem, where readablity is more important than
the speed of the produced binary (or the speed of development), the 
amount of highlevel language commands is low and the highlevel language 
commands are wide spreaded (and the problem may (currently) not contain
floating-point problems. 

I guess the speed of the produced binary is 2-5 times slower than the binary of
optimized Assemblercode and in very most cases (1.5-3) times slower than the
binary, which comes out of the C-compiler.
So I think the output of formula is not too slow for the some/most parts of 
your program (and formula/alumrof supports a good maintainable method to 
optimize it's output)

You would not have the conversion time problems, if you use the C-version 
of this program on your workstation, or port this C-code back to the
acorn archimedes (needs portation of parts of ICON 8.6 and maybe you will
get memory-problems...).
      
Cause the assemblercode output of formula is full relocatible on the acorn 
archimedes (this makes access of global far away data slow) and routines
to access Wimp-routines still not exist, most programs written in formula
for the archimedes have filetype MODULE or UTILITY.
 
One new feature of the version 0.8:
You can now also insert formula-commands in the outputfile of formula and
then rerun it through formula (which decrease convertion time...) and
with the included !alumrof, you can restore (most) of your inputfile from
the outputfile of the first outputfile.  

=============================================================================
Before you read on, you should check, if you have the programs formula need !

You need at least:

iconx (part of ICON8)  (Freeware by THE ICON PROJECT/ported by P. Moore)
      is needed to run the formula/alumrof programs itself
tla   (Version > 0.1H) (Freeware by F. Lancaster)
      is needed to use the output of formula

formula is also Freeware.

You should also check, if you have enough ram-memory to run this version of 
formula (minimum about 608K)
==============================================================================


have success ! (and don't forget to send me a message, if you found a bug...)

so long
MUFTI

(currently zrzm0370@helpdesk.rus.uni-stuttgart.de)

_______________________________________________________________________________

Table of Contents:

1.   Invoking formula and alumrof

2.   Problems about working with TLA

3.   Modifing the output of formula and getting back your inputfile

4.   Used and Reserved Registers

5.   Other Freesoftware needed to use it (no special hardware needed)

6.   Commands for formula 

7.   Operands

8.   Operators 

9.   Arrays

10.  Pointers

11.  Functions

12.  Structures

12b. Be careful with using Registers in a Formula-program

14.  Configurations

15.  Using Make to reduce turn-around-time

16.  Producing other filetypes as ABSOLUTE

17.  Copyright notices

18.  Thanks to other Freeware-programmers 

19.  Changes from older Versions

20.  Known Problems

21.  Resones, If it don't work

22.  If you got problems


Appendix A: Important files 
===========================

Appendix B: !formula08.functions
================================

Appendix C: !formula08.func_form
================================

Appendix D: Building full macro-assembler macros  
================================================

Appendix E: How the stack looks in a function/macrocall
=======================================================

search for TRAP in this file ...
______________________________________________________________________________


1.  Invoking formula and alumrof
====================================

formula is now a 1/4 Wimpprogram. 
Depending on the system variable,
formula$pollevery
it can work outside the desktop or as a simple wimptask with wimppolling. 

if formula$pollevery is less then zero, formula can be used outside the desktop
The bigger formula$pollevery is, the lesser will be called the wimppoll routine

There are a few simple applications (like !star4mula or !wformula) as connection
to common desktop-interface programs (like !Star or !TinyDirs)

If formula starts the first time, it will set it's defaults 
(there are a lot ...)
It will inform you about this defaults, by viewing a textfile (the normal way
it shows error- and warning-messages).

You can control the method of viewing this textfile by exchanging 
<formula$viewer> (errormessages, default is *run the file) and 
<formula$forkview> (warnings, default is *list the file)
These viewers are also used in showing error and warning-messages.

______________________________________________________________________________

other important systemvariables are

variable            default       discription

formula$listlen     50            this defines the length of arrays
ICON$BLOCKSIZE      110000        internal memory requirement of iconx
formula$minwimpslot 608K          minimal Wimpslot 
formula$maxwimpslot 608K          maximal Wimpslot

Be sure, that this variables are big enough for program
______________________________________________________________________________ 

 syntax for starting formula on commandline:

 formula [-listing] outputfile inputfile
  
 this writes the assemblerfile to <formula$work>.target_asm
 then build a outputfile (binary or AOF) from it.
 -listing is optional
 with -listing, you get a assemblerlistingfile (<formula$work>.listing)

 or 

 <formula$dir> -make outputfile1 inputfile1 outputfile2 inputfile2 ... outputfileN inputfileN

 (the outputfiles are macroassemblerfiles)
 this is useful for splitting the programs in parts (which reduce the time of
 conversion of the whole program).
 the make-program you can manage what files need to be reconverted.
 you must have a main-program, which includes your splitted files und the file 
 <formula$dir>.tlastartup to use this file as inputfile for TLA  

alumrof is also a 1/4 Wimpprogram.

Depending on the system variable,
alumrof$pollevery
it can work outside the desktop or as a simple wimptask with wimppolling. 

The behavour is like formula$pollevery.

 syntax for staring alumrof on commandline:

 alumrof outputfile inputfile

 where inputfile is a (output)file made by formula and outputfile is a file,
 which can be used as inputfile for formula.

Alumrof is made to restore your formulacommands, if you modified the output
of formula.


2. Working with TLA
===================

TLA expects as before the first code producing Assemblercommand the command:
   .PROC
This command normally comes with the !formula08.tlastartup/!formula08.tlastatrel
file (which contains initialsation-routines and needed assemblermacros), you
should not use it in your file.
TLA expects as last command in the file:
   .END
You must include this command as last command in your file.

There is a problem, if you convert assembler for other Assemblers to TLA
First, dezimals are followed by . and hexdezimals may not contain &
(this is only important for your assembler parts, formula will use 
decimals as normals und use 0x for hexadezimals)

Some mystic things may tla crash for formula-output-files:

1. It may crash, if you don't assemble with the  -bl null: option
2. It may crash, if you use some list-option commands (like .LIST, .NOLIST ...)

This problem is the reason, why the conversion of TLA may take a longer time
you would guess.
If someone knows more about this problem, please let me know. 


3. Modifing the output of formula and getting back your inputfile
=================================================================

 formula can work with it's own (modified) outputfile.
 almurof can restore the recent formulacommands from a outputfile of formula

 The process of building a formula-program may look like this:
 
               editor
assemblerfile --------+
                      |                    
       almurof        v       formula               assembler
     +---------> formulafile ---------> outputfile -----------> binary
     |                                      |
     |                                      |
     +------+<------------------------------+
     |      |
     |      v       editor                       formula               assembler
     |  outputfile -------> modifiedformulafile ---------> outputfile -----------> binary
     |      ^                                                 |
     |      |                                                 |
     +----->+<------------------------------------------------+
     |      |
     |      v       editor                      assembler
     |  outputfile -------> modifiedoutputfile ----------> binary
     |      ^                       |               ^
     |      |                       |               |
     +------+<----------------------+         be careful with
                                        stackregister/tempregister/flags

 
 assemblerfile       is a file without any formula-related data 
 formulafile         is a file with formula-(and assembler-)commands
 modifiedformulafile is a outputfile of formula with new or changed 
                        formulacommands 
 outputfile          is a outputfile of formula 
 modifiedoutputfile  is a outputfile of formula with new or changed 
                        assemblercommands 
 binary              is a runable binary 


 Cause a modifiedformulafile contain less formulacommands than a formulafile,
 the time to run formula for modifiedformulafiles is faster, than run formula 
 on formulafiles.
 This fact is useful if you develop your program with the (very faster) 
 C-version on a workstation and only have to debug a few things, when you 
 came back to your homecomputer. 

 In the outputfile, the formula-commands will be expanded to macro-assembler-
 commands, comments and other formula-commands. 

 The macro-assembler-commands are used to produce a runable binary.
 Comments show which formula-command is expanded and which for part of the
 expression the next macro-assembler-commands are. These comments are used
 for documentation and if you want to optimize the output by hand.
 Other formula-commands are needed to hold information for the next run of
 formula (e.g. which registers are need to be saved, or how a symbol was 
 declared) or contains information for !alumrof.
 
 Information for !alumrof is in the outputfile of forula in the structure:

 ;==>
 ...
 ; comment with the original formulacommand  
 ...
 ;<==

 If you destroy this structure, almurof can't work properly.
 You should touch this structure only under the following conditions:

 1. You want to remove this formulacommand
      You should erase all from (including) ;==> to ;<==
 2. You want to change the orignal formulacommand
      You should erase all from ;==> to the line above the comment with the 
      original formulacommand
      You should erase all from the line below the comment with the 
      original formulacommand to ;<==
      You should change to comment with the original formulacommand to the
      changed formulacommand
 3. You want to optimize the assemblercommands generated by formula
      You must change ;==> to ; ==>
      You must change ;<== to ; <==
    otherwise the next run of alumrof deletes your optimizations (and restores
    the orignal formulacommand) and the next run of formula will use the
    optimized code with the wrong copy of the stackregister.
    Later, if you want to maintain your file and you want to get back the 
    orignal formulacommand, you change in this block ; ==> to ;==> and
    ; <== to ;<==. Now you can run alumrof and the orignal formulacommand will
    be restored.

 For all other cases, you should not touch the block between ;==> and ;<==.
 Insert new formula or assembler commands outside this blocks.
 (between ;<== and ;==>)  
 If you insert assemblercommands, which change stackregister or work (with
 your copy of) tempregister or the flags (this is only possible, if you use 
 the defaults (see below)), you should rerun formula before you assemble.

 TRAP: You should not modify a outputfile by changing/insert something 
       in a structure definition (between ;DEFSTRUCT and  ;ENDSTRUCT) or
       in local declarations (inside a function/macro)
       or you should a once use alumrof.
       Other currently converted formulacommands are already assume the 
       structoffsets/stackoffsets of the older runs.

 if you got no "slow-construct" warning at the last run of formula, you may 
  insert a new local declaration at the end of the local data block.
  You can also insert new declarations at the end of the structure.

4. Used and Reserved Registers
==============================

 For internal Operations formula must also use registers. For it's internal
 stack it uses the register named "stackregister".
 By default, formula uses R12 as "stackregister" (to avoid incompatiblibility
 to other language-processors (if you want to link AOF-files together with 
 them, which often uses R13). If you want to change saveregister see in 
 chapter "Configurations". 

 Without it's stack (pointed with stackregister), formula will produce all
 sorts of errors.
 Therefore formula saves by default the contence of stackregister (which makes
 the binary slower and longer). 

 ***************************************************************************
  if you change the default of saveing and restoring stackregister, then it 
  must be sure, that the next formula-command see the stackregister 
  (default R12) of the last formula-command !!!!!!!!!
 ***************************************************************************

 "tempregister" (default R11) will be destroyed in internal operations, so it 
 saves and restore this register (by default) to and from stack. If this is
 not necessary, you can change this option (see in chapter "Configurations").

 As default Formula doesn't use R13 and R14. you can use them as
 (stackregister/tempregister) or do other things with it.

 The rest of the registers, (default R0,R1,R2 ... R10) will be used and
 destroyed by formula. You can forbid and reallow the destoring of this 
 Registers with the ;SAVE and ;FREE commands. See in chapter "Be careful with 
 using Registers in a Formula-program"

 
5.  Other Freesoftware needed to use it (no special hardware needed)
====================================================================
 
 If you want to use this implementation of formula, you must/should have the
 the following programs (for each there is a freesoftware-implementation for
 Acorn Archimedes)
 
 -------------------------------------------------------------------------------
 iconx  written by THE ICON PROJECT/ported by P. Moore
        you must have this program 

 TLA    written by Frank Lancester 
        you must have this program
 
 Make   written by Free Software Foundation (GNU) ported by Paul Moore
        useful to reduce turn-around-time, but not necessary

 M4     can be used as a CPP -like preprozessor
        useful, but not necessary
 -------------------------------------------------------------------------------

 ICON8 is the language the main part of formula is written in.
 Under Unix, icon can be converted to C, so you can do crossdevelopment on
 your workstation. 

 To produce runable code, you must have a macro-assembler.
 For this implementation you must have TLA (version 0.1h), but it's not too
 difficult to implement it on other macro assemblers (or other architectures)
 If you want to do this, contact me. 
 
 Make can reduce the turn-around-time, cause you can easy split your program
 in parts. Normally Make is used via object-files, but you can also join the  
 the converted macroassembler with including them in the main-program (e.g. 
 with the ".INCLUDE" command in TLA)  
 This is useful cause there is no PD/Shareware/Freeware linker/loader on the 
 Acorn Archimedes. Cause of the same reason, it runs as default via TLA as
 binaryproducing program. Cause TLA can also produce a AOF-object-file, you 
 can use Make in a normal way see chapter "Producing other filetypes as 
 ABSOLUTE".
 
 There is no special hardware needed.
 It runs on every Archimedes or BBC A3000, which has 608KB next-memory free
 (after the load of Clib and FPEmulator). 
 A fast diskdevice to store at least 200KB (!formula08.formula08) would be
 useful (eg. RAM-disk or Harddisk).
 Inputfiles with big expressions may need more memory ...
 Formula and all other matching programs fit to a single 800KB floppy disk. 
 Hardware which may increase speed:
 -  a harddisk
 -  more memory for a ramdisk
 -  ( ??? i don't know if a Floating-Point-Unit would speed up iconx )
 -  a real fast machine for cross-convertion with the C-version 
    (you will need then other parts of icon8.6 too (rt.a) and a sturdy 
     C-compiler (eg. gcc))     
    such machines can be SUN, IRIS, HP, APOLLO, DEC, IBM RS6000, I860, I486 ...
    (
     e.g need the conversion of the file !formula08.func_form (99 lines) on the
     archimedes ARM2 (interpreted by iconx) 47 sec
     SGI 4D-25       (compiled with gcc)     4 sec    
    )
 -  fast network-connection to the real fast machine (e.g. TC-PIP, optimal NFS) 
    ( if you can't access the real fast machine and you acorn archimedes the 
      same time, the usage of modified output of formula as input of formula
      is useful )


6. Commands for formula
========================
 
 All commands begin with a comment-sign, to allow easy syntax-checking
 of the assembler-part (here ; for TLA).

 The commandname must be in UPPERCASE (eg. ;if will be ignored) 
 
 Cause formula can handle conversions between difficult types,
 you must declare all variables and functions. This is currently made 
 by: 
 
     ;DECLARE <type> expression
     ;<type> expression                           (not for functions)
 
 For <type> is INT, CHAR, INTPTR, CHARPTR, STRUCT <structname> or
 STRUCTPTR <name> possible. (PTR means pointer to)
 If you account with Pointers, they will be always converted to integer !
 ========================================================================
 (be careful C-freaks !)
 For Function declaration, VOID is also valid.
 FLOAT is only useable for the conversion-part, but there is no Macro-assembler-
 implementation (e.g. there is no FLOATsum -macro ...) 
 
 where expression is the name of a variable
 if you use ;DECLARE it may also be a arraydeclarator or a functiondeclarator
 (see below).
 
 If it's used for arrays, expression must be in the form: 
 name[dimension1,dimension2,dimension3, ... dimensionN]
 
 If it's used for functions, expression must be in the form: 
 name(argtype1,argtype2,argtype3, ... argtypeN)
 
 ;DECLARE doesn't reserve memory, it may be used to declare symbols which are
          in a other includefiles.



 Other commands are:
 ------------------- 
 
 for evaluation:
 
     ;LET variable=numerical_expression
 
 for conditional program-parts 
 
     ;IF logical_expression
      ...
      ...
     ;ELSEif logical_expression
      ...
;this is optional 
      ...
     ;ELSEif logical_expression
      ...
;this is optional 
      ...
     ;ELSE  
      ...
;this is optional 
      ...
     ;ENDIF

 for a for - loop

     ;FOR (variable=numerical_expression;logical_expression;variable=numerical_expression)
      ...    
      ...
     ;ENDFOR

 for a while - loop
 
     ;WHILE logical_expression
      ...
      ...
     ;ENDWHILE
 
 for a do-while - loop
  
     ;DO    
      ...
      ...
     ;ENDDO logical_expression 
 
 for a function definition:

     ;FUNCTION <type> expression
      ....
     ;RETURN numerical_expression   
  ;  return should used, if type is not VOID, but may not used if type is VOID
      ....
     ;ENDFUNCTION

 for a function (that will be inlined) definition:

     ;MACRO <type> expression
      ....
     ;RETURN numerical_expression   
  ;  return should used, if type is not VOID, but may not used if type is VOID
      ....
     ;MACROFUNCTION

 for definition of a struct

     ;DESTRUCT structname
      .....
; some varible declarations
      .....
     ;ENDSTRUCT

 for inclusion of other files

     ;INCLUDE filename

 for reserving a register

     ;SAVE register1,register2 .... registerN

 for free a reserved register

     ;FREE register1,register2 .... registerN
 
 for usage of formula inside macros 
     (labels marked as local, this prevents from "label multiple defined" error)

     ;INSIDE

 for usage of formula outside macros

     ;OUTSIDE
 
 commands described earlier:

     ;<type>    variable
     ;<type>PTR variable
     ;DECLARE   (various arguments)
     ;STRUCT    structname variable
     ;STRUCTPTR structname variable


 there are also internal formula-commands, which are important, if you insert
 commands into the output of formula (be very carefully in touching them, 
 if you something wrong with them, you may lose information for the rebuild of
 formulacommands with !alumrof, of the next run of formula produce bugs)

     ;==>
      ;a formula-command was expanded in this zone 
      ;forbidden zone
      ;you may not/should not insert new formula-commands in this zone
      ;if you want to erase a formula-command, you have to
      ;delete it's whole forbiddenzone (anything from ";==>" to ";<==")
      ;If you want to optimize the assembler in this zone by hand, you should 
      ;change ";==>" to "; ==>" and ";<==" to "; <==". Otherwise the next run 
      ;of !alumrof will restore the orignal formulacommand and delete the 
      ;optimized code
     ;<==

     ;SAVEREGISTER
     ;RESTOREREGISTER

     ;GENERATION


  If a line with a Formula command which are longer is used,
  the line must end with the \ sign and the next line must be leaded by ; 


 In numerical expressions are available:
 ---------------------------------------
 
   Numerical variables, numerical constants, numerical operators, functions,
   parenthesises and arrays.
 
 
 In logical expressions are available:
 -------------------------------------
    
   Logical Variables, logical constants, logical operators and numerical
   expressions.


7. Operands
===========

 Variables 

 Variables have to be declared. 
 They may include every character and substring, which is not operator and
 is valid for the macroassembler. 
 Logical Variables means "false" if the are 
 equal zero (0) otherwise they mean "true".


 Constants

 Numberical Constants may be decimal or hexadecimal. Hexdecimal constants
 must have a 0x prefix. 
 Logical Constants are zero and not zero (analog to logical variables). 
 String constants must be inside " signs
 Inside String constants the " sign is quoted by \"
 For character constants a character must be inside ' signs.

 
8. Operators
============
 
 Here is a list of available Operators (the list shows also the 
 priorities of the operators (monadic operators do not need priority) 
   
 Upper in the list of priorities than the operators are the constructs:

         () for  parenthesis or functions
         [] for  arrays
         ,  for  functions and arrays
         .  for  access struct
         -> for  access pointer to struct 

       monoadic operators: (operator operand1)
         
         numerical operators:
          
         -  for numeric negation
         (CHAR)  conversion to character type
         (INT)   conversion to integer   type
         (CHARPTR)  conversion to character pointer type
         (INTPTR)   conversion to integer pointer   type
         ~  bitwise inversion   
         *  load/store contence of adress
         &  generate adress (if possible)

         logical operators:
         
         !  for logical negation
 
       dyadic operators (operand1 operator operand2)    
   
         numerical operators 1:
   
         /  for  divide                  currently not available for CHAR
         %  for  modulo                  currently not available for CHAR
         *  for  multiply                currently not available for CHAR
         -  for  subtract         
         +  for  sum              
         << for  shiftleft
         >> for  shiftrigth         

         logical operators:      
   
         == for   equal           
         != for   notequal        
         >= for   greaterequal
         <= for   lessequal       
         >  for   greater         
         <  for   less         
         && for   and             
         || for   or        

         numerical operators 2:
         &  for   bitwise and
         ^  for   bitwise eor
         |  for   bitwise or
   
 If you need more (new) operators, ask me, it's not too difficult for me to 
 implement them

   
9. Arrays
=========
 
 Arrays are used in the form 
  array_name[dim1,dim2,dim3, ... dimN]
 or
  array_name[dim1][dim2][dim3] ... [dimN]
 Where dim1 ... dimN are other numerical expressions.
 In the last row of the array, the single values follow each other.
 Arrays are available left and right of the "=" sign.
 For declaration use: 
 
  ;DECLARE type array_name[dimension1][dimension2][dimension3][ ... dimensionN] 
  
 or
  
  ;type array_name[dimension1][dimension2][dimension3][ ... dimensionN] 
 
 Where dimension1 ... dimensionN are Integer-constants.

 To access arrays, you can also use pointers.

 array_name[array_name,dimension1,dimension2,dimension3, ... dimensionN] 
 is equivalent to 
 array_name[dimension1][dimension2][dimension3][ ... dimensionN] 

 If you use a register as default, it will access a integer at the offset
 in bytes. 

 You may also declare registers as arrays:
 then you will access this type at the offset of this type

 
10. Pointers
============

 Pointers do not contain data, they contain adresses of data.
 They declared with the PTR extension to the type (e.g. ;INTPTR or ;STRUCTPTR)
 If you account with pointers, they will be converted to integer 
 (TRAP: unlike C !!!) 
 To get adresses you can use the & operator.
 To access the data in the adress in such pointers use the * operator.

 e.g.
 ;INT    data
 ;INTPTR pointer
 ;LET    pointer=&data
 ;LET    *pointer=1
 ;LET    writeint(*pointer)

 Pointers to Pointers are not allowed, but arrays of pointers.

 e.g.
 ;INTPTR pointerarray[40]
  

11. Functions
=============
 
 Functions are called with function_name(arg1,arg2,....argN)
 
 Where arg1 ... argN are numerical expressions.
 Strings ( in the form: "BLA-BLA" ) are also allowed.
 
 To define a function, you must define the function in the form

 ;FUNCTION resulttype function_name(type1 arg1,type2 arg2,.... typeN argN)
 ....
 ;RETURN numerical_expression ;if 
 ....
 ;ENDFUNCTION

 where typeX is in this implementation INT or CHAR (maybe FLOAT), and if the
 argument is a array, INTPTR or CHARPTR (maybe FLOATPTR).
 typeX argX may be replaced with ... ,which declare the function with a various
 number of argument.
 resulttype can also be VOID. If you use VOID, you may not use ;RETURN,
 if you not use VOID you should use ;RETURN.

 There are two different ways to handle Array-arguments:
 1. The C-like way
    In C you only pass the name of the pointer, and you can access the 
    contents with array[offset]. This is very useful for strings (Arrays with
    1 Dimension).
 2. The FORTRAN-like way
    In FORTRAN you pass the name of the array and declare later the dimensions
    of the array. This is very useful for multidimension Arrays.
 In formula, you may use both constructs.
 If you pass a array with 1 dimension, you only need to write the argument as
 typePTR.
 If the argument is a multidimension array, you need to write the argument as
 typePTR and then must follow a ;DECLARE declaration of this array behind
 ;FUNCTION        ====
 
 two examples: 

 1. 
        ;FUNCTION dim1(CHARPTR string)
          ....
        ;LET string[1]=32
          ....

 2.     ;FUNCTION dim3(CHARPTR matrix)
        ;DECLARE CHAR matrix[5,6,7]
          ....
        ;LET matrix[1,2,3]=32

 Before a functioncall, formula saves all already used registers to stack,
 and restore them after the call.
 Therefor a functioncall is slow, but you can do inside the function all
 you want (e.g. crunsh all registers execept stackregister).

 instead ;FUNCTION/;ENDFUNCTION can also be used: ;MACRO/;ENDMACRO.
 The function will then be inlined. You can't call such a macro recursive.

 In this Implementation there is a TRAP for recursive-calls which define
 local arrays or local structures. Cause the macro "formula_malloc" use
 currently static data, this arrays or structs are not local.
 Change "formula_malloc" if you need to do this.


12. Structures
==============

 Structures are made to define new complicated types.

 They are defined with

 ;DEFSTRUCT structname
    ...
    ;<type> structmembervariable
    ...
 ;ENDSTRUCT
    
 To declare variables with this new type, you have to use:

 ;STRUCT structname structvariable
 or
 ;STRUCTPTR structname structpointervariable

 You can access this structs with the . and the -> operator.

 structvariable.structmembervariable
 structpointervariable->structmembervariable


12b.  Be careful with using Registers in a Formula-Program
==========================================================

 You must be careful with using Register inside and outside of formula-commands.
 Normally formula will destroy the contence of one of this registers early.

    (e.g.) look at this example:

     LDR R1,x
     ;LET x=3+4*4+1
     STR R1,y                <=== bug
    
    R1 will be used inside evaluating x=3+4*4+1 and will be destroyed (y!=x)
    R1 will be undefined.    

 Therefore there are a exception, which forbid formula to use this register.

 You give a explicit ;SAVE-command:

     LDR R1,x
     ;SAVE R1
     ;LET x=3+4*4+1
     ;LET x=x+1
     STR R1,y                <=== ok (x=y)

 If you use registers as operands inside there are two other exceptions.
 Currently you can use R0,R1,R2,...,R10 as operands. 
 Normally formula also destory the contence after use.

     LDR R1,x
     ;LET x=3+R1*4+1
     STR R1,y                <=== bug 
    
 R1 (and therefore y) are undefined.

 The first exception is that the register is used more than one. 

     LDR R1,x
     ;LET x=3+R1*4+R1
     STR R1,y                <=== ok (y=x)

 The other exception is that the register is the 1. operand

     LDR R1,x
     ;LET R1=3+4*4+1
     STR R1,y                <=== ok (y=20)

 This exceptions and ;SAVE forbid the use of the register in the following
 lines, till the end of the file or a ;FREE-command occurs.
  
 One dangerous case, is the request of a new register in a loop.
 Cause this request is not known at the begin of the loop, this register
 may be temporary used (and destroyed) in the loop before the request and
 after the loop.

 To request the register before the loop, use ;SAVE.

 See the following example:

 ;LET nix=1 
 ;WHILE nix<10               <=== R0 is free for temporary use
    ;LET nix=nix+1           
    ;LET R0=nix*nix          <=== from here R0 is saved
 ;ENDWHILE
 ....                        <=== R0 is not 100, cause it may be destructed  
                                  by the while-loop-test

 To make this example proper, you need a ;SAVE before the loop

 ;LET nix=1
 ;SAVE R0                    <=== from here on R0 is not free for temporary use
 ;WHILE nix<10               <=== R0 is not free for temporary use
    ;LET nix=nix+1           
    ;LET R0=nix*nix          
 ;ENDWHILE
 ....                        <=== R0 is 100

 Cause this sort of bug is very difficult to find, you will be warned, if 
 you request a new register inside a loop. 
 

 Formula also need registers to do something, so don't forget to give back
 registers. If Formula run out of useable registers cause of less ;FREE 
 commands, it will give a error-message.

 If you give the commands:

 ;SAVE R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10
 ;LET x=x+1                  <=== bug  where to load x ? (no registers free...)
 

14. Configurations
==================

 You can configure a few things (in the <formula_tlaconfig$dir>.tlaconfig 
 -file):

 a. Always saveing and restoring R11 and R12 between the macros make the
    binary big and slow.
    You can change this with altering formulaR11flag and formulaR12flag,
    but then you must save and restore R11 and R12 for yourself. 

 b. There are 4 different integer-division routines.
    Normally the shortest and slowest routine is used (INT-DIV.SHORT),
    Cause this reduces the time of macro-assembling.
    If you want to use a faster routine, change the name in the .INCLUDE
    command.
    The routine of Graeme Williams produce the fastest binary. 


15. Using Make to reduce turn-around-time
=========================================

 Long Input-files result in painful long time to wait till the thing is 
 ready. 
 Therefore it's useful to split the program in parts. If you changed one
 part (one file), you have only to reconvert this file. The Make-program
 searches automatically (by using the time-stamp-information), what files
 must be worked.
 The global declarations can be included into the parts with the 
 ;INCLUDE -commands.
 Your main-program must include the !formula08.tlastartup file (or the 
 !formula08.tlastatrel (see below)) and the !formula08.functions -file if
 you want to use the programs inside.
 Now you must use the -make -option in the commandline, to protect
 again the inclusion of tlastarup-file and the run through TLA.
 Only to produce the final binary, tlastartup-file and the parts must be
 included and TLA must run.
 ========================================================================
 If you use the -make option, loops and conditions must be inside
 macros and ;FUNCTIONs (only 1 file/block may contain ;OUTSIDE -constructs).
 ========================================================================
 See the !makeuse- demo for a example.


16. Producing other filetypes as ABSOLUTE
=========================================

 Cause the current implementation of the macros, which are called by formula, 
 are full relocatible, you can also produce other filetypes than ABSOLUTE.
 You can also produce linkable AOF or UTILITY or MODULE -files.   
 Cause the tables for modules are a little bit complicated, you can also 
 produce a SIMPLE_MODULE, which is a module with 1 entry from commandline,
 but you need to define less adresses. 

 select what type of outputfile you want with setting FALSE to TRUE
 settype outputfile utility    is needed for UTILITY
 settype outputfile module     is needed for SIMPLE_MODULE and MODULE

ABSOLUTE      .EQU FALSE
AOF           .EQU FALSE
UTILITY       .EQU FALSE
SIMPLE_MODULE .EQU FALSE
MODULE        .EQU FALSE

 if you set AOF to TRUE, you need the information for the current name
 of the procedure (in AOF-files you may need more then one procedures cause 
 of linking multiple AOF-files)
 include the following in your file before you include this file (include the 
 macro and not the .PROC command) and change the term 
 "select_a_name_of_procedure" if neccessary

 .MACRO select_a_procedurename 
  .PROC select_a_name_of_procedure
 .ENDM 

 if you set SIMPLE_MODULE to TRUE (result is a module with 1 entry via
 commandline with the Command_keyword) you need to define the following
 adresses somewhere behind you include this file (jump over this strings
 or place it after the SWI XOS_Exit)

Title_string       (adress of a string of module title)
Help_string        (adress of a string with text of help command)
Command_keyword    (adress of a string with Command_keyword to start program)

 if you set MODULE to TRUE, you need the information for the module-header
 if a feature should not be available use the .EQU 0 command else use the
 name as adress
 include the following in your file before you include this file
***************************************************************************
 WARNING: with MODULE there may be a direct jump to a adress via 
 Check that no formula-command is invoked without the initilisation with the
 macro "formulainit" (it sets up the stack of formula and do other things)
***************************************************************************

Start_code                     .EQU 0
Initialisation_code            .EQU 0
Finalisation_code              .EQU 0
Service_call_handler           .EQU 0
Title_string                   .EQU 0
Help_string                    .EQU 0
Help_and_command_keyword_table .EQU 0
SWI_chunk_base_number          .EQU 0
SWI_handler_code               .EQU 0
SWI_decoding_table             .EQU 0
SWI_decoding_code              .EQU 0

(note:
       for MODULEs, SIMPLE_MODULEs or UTILITYs formula saves all register 
       in "formulainit" to formularegistersave+(registernumber*4) 
)
 
17. Copyright notices
=====================
 
 freesoftware means: The copyrights belong to the author (here MUFTI),
 but may use it.
 You may also copy the program to any media, if you don't get money for this
 and you include the copyright-statement-files.
 (if you want to know more about copyright of formula, look into the 
 file !formula08.copyright)).


18. Thanks to other freeware programmers
========================================                 

 Thanks to Frank Lancester              (TLA and some help for the LD/ST macros)
 Thanks to Paul Moore                        (Icon8, Gawk and Make)
 Thanks to Conrad Hughes and Graeme Williams (fast integer division routines)  
 Thanks to Guido Thather                     (Gawk_l) 

19. Changes from older Versions
===============================
 
 ***********************************************************************
 WARNING:
 ***********************************************************************
  this Version 0.8 is not compatible to earlier Versions, before 
  Version 0.6
  There are differences, how to declare a function and how to reserve memory
  for a array. 
  Arrays are now not longer implementated as pointers (this was in Version 0.5
  and Version 0.51).
  Functions handle now it's arguments via the Stack (to make reentrantance 
  possible this was version anno dunnemals)
  Old sources should be reconverted ...
 ***********************************************************************

 
20. Problems:
=============
 
 The macro-implementation of formula isn't ready yet.
 Currently it performs only two datatype
  (INT = Integer-type, CHAR = charactertype).
 FLOAT = floating-point-type could be handled from the icon-part of formula,
 but there is no implementation of the produced macros ( e.g. there is no
 FLOATsum ).
 Cause there is a FPU-emulator for the Acorn Archimedes, it's possible to
 write this without big pain, but both current version of TLA and the current
 version of the author have problems with it...
  
 Like High-level-language-tools the binary output of formula isn't ideal.
 Possible is a better optimization inside the code-producer, and a optimation
 run after the code-producer, but currently the required time for conversion
 is to high for this ...    
 

21. Resones, If it don't work
=============================

This is a short checklist, if something goes wrong.
I'm not real sure, if it contains all errorsources ...

  - you got a error-message like:
    not found
    
    - check if you have all needed programs: TLA (version 1.h) and iconx
    - check if the systemvariables <icon$path> <tla$path> are set
      correctly

  - after usage of iconx the program tells you something about:
    unexpected error
    (syntactical errors are normally messaged correct)
   
    - check if you have enough next memory (minimum 608 KB is needed,
      depending on length of inputfile) 
    - check if you have a big enough icon$blocksize
    - check if you have big enough wimpslots (formula$max/minwimpslot) 
    - check if you have enough free discspace
    - check if there are open files
    - check if the used paths became too long to fit into the possible 
 
  - tla stops with a resonable errormessage

    - check if you have enough free discspace
    - check if there are open files 

  - tla stops with a mystic errormessage

    - check if the -bl option of tla is used 
    - check if you have some .LIST .NOLIST usw. commands
    - check if there is a multiple macrodefinition
      you can find this multiple macrodefinition with examinating the last 
      performed assemblercommand in the listing-file    
      check it you included tlastartup/tlastatrel or functions twice
    
  - start of output give strange results
   
    - check if you use the right tla-version
      most programs run only correct with tla version 0.1h
    - maybe it's a fault of formula, please contact me.  


22. If you got problems
=======================

 Questions and Bugmessages are wellcome. 
 All ideas and opinons are wellcome.
 
 so long
 MUFTI
 
 currently 
 (
 internet: 
 zrzm0370@helpdesk.rus.uni-stuttgart.de
 
 this is from janet:
 zrzm0370%de.uni-stuttgart.rus.helpdesk@nfs-relay
 
 bitnet: 
 ZRZM at DS0RUS1I           (will end April 1993)

 (
 if you got problems with the mail-exchanger you can currently reach me with
 telnet rusmv1.rus.uni-stuttgart.de
 login: info
 (no password)
 select the command 
 contact 
 and tell the program, you want to send a message to me
 )
 )

ps: sorry for my "bad english" 


Appendix A: What the important files mean 
=========================================

Directory !formula08 (can be set with <formula$dir>)

File !formula08.!helpfile
     text with this document
File !formula08.copyright  
     file with copyright notices
File !formula08.formula08   
     the iconx executable, which do most of the work
File !formula08.functions  
     file with lowlevel functions 
File !formula08.function_h 
     file with declaration headers of functions 
File !formula08.func_form 
     file with functions written in formula, currently a example for simple 
     formatted stdin/stdout IO 
File !formula08.go
     default file with go macros (this macros are used in loops and conditions)
     with setting <formula_go$dir> you can use your own file and can easily 
     insert code (via the go macros) in your program, which needs often to be
     called (eg. wimptasking)
File !formula08.tlaconfig  
     default configurationfile of tlastatrel
     with setting <formula_tlaconfig$dir> you can 
File !formula08.tlastartup   
     includes tlastatrel and functions and select filetype ABSOLUTE
File !formula08.tlastatrel   
     contains the macros which are called by the output of formula (except the
     macros, which are in <formula_go$dir>.go 

Directory !formula08.intdiv   

File !formula08.intdiv.hughes    
     fast integer division routine posted from Conrad Hughes to comp.sys.acorn
File !formula08.intdiv.mufti   
     integer division routine posted from MUFTI to comp.sys.acorn
File !formula08.intdiv.short   
     short integer division routine
File !formula08.intdiv.williams  
     fast integer division routine posted from Greame Williams to comp.sys.acorn

Directory !formula.work  (can be set with <formula$work>) 
     Directory for the following outputfiles of formula:

     error      errormessages
     warning    warningmessages
     target_asm macro-assembler-output (if no -make -option)
     listing    assembler listing (if -listing option)

This files can placed by you with a set command:

<formula_tlaconfig$dir>.tlaconfig 
     your own tlaconfig -file:
<formula_go$dir>.go
     your own file for go-macros (this macros are used in loops and conditions)

files you need to use formula and not included (they are freeware):

<iconx$path>iconx   icon language token executor 
<tla$path>TLA      tla macroassembler version 0.1h
TLA_Errors         file needed by TLA

Appendix B: formula.functions
=============================

 With this implementation come a few lowlevel functions. They are included
 as default if you don't use the "-make" -option.
 To include them if you use the "-make" -option, use exactly one time in the
 main/assembler-file:

 .INCLUDE <formula$dir>.functions

 (this command is only valid for the assembler (TLA))

 To include the needed function-headers, include in every file with 
 formulacommands: 

 ;INCLUDE <formula$dir>.function_h

 Don't see in this functions something like a "language"-standart, they are
 only the functions I work with. If you don't make money with a redistribution
 and distribute it not with the archive/disk of formula itself,
 you may add, change, rename or delete functions in this (or a other) file. 
  

;DECLARE INT     errorflag
 This flag (variable) is set from the errorcheck-macro after a mySWI X.. 
 -command. You can find here, if some calls find a error.

;DECLARE CHARPTR errorblock
 This pointer directs to a RISCOS-errorblock (text lies at errorblock[4]) 

;DECLARE VOID perror()
 reports last error

;DECLARE INT     strlen(CHARPTR sourcestring)
 returns length of sourcestring

;DECLARE INT     strcpy(CHARPTR targetstring,CHARPTR sourcestring)
 copies sourcestring to targetstring, returns number of copied characters

;DECLARE INT     strcmp(CHARPTR targetstring,CHARPTR sourcestring)
 returns -1 if targetstring is less, 1 if targetstring is greater and 0 if
 targetstring is equal in a lexical comparison of the strings.

;DECLARE INT     strcat(CHARPTR targetstring,CHARPTR sourcestring)
 appends sourcestring to targetstring, returns number of appended characters

;DECLARE INT     strncpy(CHARPTR targetstring,CHARPTR sourcestring,INT length)
 copies maximal length characters from sourcestring to targetstring, returns
 number of copied characters

;DECLARE VOID     writestr(CHARPTR string)
 writes string to the screen

;DECLARE INT     readstr(CHARPTR string,INT maxstringlength)
 read maximal maxstringlength characters from keyboard

;DECLARE CHARPTR int2string(INT number)
 returns a stringpointer with the decimal stringconversion of the integer number

;DECLARE CHARPTR int2hexstring(INT number)
 returns a stringpointer with the hexidecimal stringconversion of the integer
 number

;DECLARE INT     string2int(CHARPTR string)
 returns a integer with the integerconversion of string (string must have a 
 & as first sign, if it is a hexadecimal value

;DECLARE VOID     writeint(INT number)
 writes decimal integer number to the screen

;DECLARE VOID    writehexint(INT number)
 writes a hexadecimal integer number to the screen
 
;DECLARE INT     readint()
 returns from keyboard readed integer
 
;DECLARE CHAR    getc()
 returns from keyboard readed character
 
;DECLARE VOID    putc(CHAR  character)
 writes character to the screen

;DECLARE INT     open(CHARPTR filename)
 returns filehandle of the opened file with the name filename

;DECLARE INT     openw(CHARPTR filename)
 as open() but opens only for write 

;DECLARE INT     openr(CHARPTR filename)
 as open() but opens only for read

;DECLARE VOID    close(INT filehandle)
 close filehandle

;DECLARE VOID     bput(INT filehandle,CHAR character)
 write character to filehandle

;DECLARE CHAR    bget(INT filehandle)
 read character from filehandle

;DECLARE INT     fgets(CHARPTR buffer,INT filehandle,INT bufferlen)
 read string from filehandle to buffer with maximal length bufferlen

;DECLARE INT     fputs(INT filehandle,CHARPTR buffer)
 write string buffer to filehandle

;DECLARE INT     eof(INT filehandle)
 check for end of file of filehandle

;DECLARE VOID    system(CHARPTR cli_string)
 currently acts pass cli_string direct to SWI XOS_CLI

;DECLARE VOID    cr()
 prints newline to the screen 

;DECLARE VOID    getclitail(CHARPTR buffer)
 reads commandlinearguments to buffer (256 chars long) (work for all filetypes) 

;DECLARE VOID    getargv(CHARPTR buffer)
 reads commandlinearguments to buffer (256 chars long) (work not for module-
 commandkeywords) 

;DECLARE VOID    getenv(CHARPTR buffer,CHARPTR varstring,INT bufferlen)
 reads systemvariable varstring into buffer ( bufferlen chars long ) 

;DECLARE VOID     setenv(CHARPTR varstring,CHARPTR varval)
 sets systemvariable varstring to varval

;DECLARE CHARPTR malloc(INT length)
 malloc will currently use SWI OS_Module 6, use free() before you exit !

;DECLARE VOID free(CHARPTR allocedbuffer)
 frees with malloc gotten memory


Appendix C: formula.func_form
=============================

This file includes some useful functions mostly written with formulacommands.
Formated IO functions are similar, but simpler than C formated IO functions.
There are 4 formatcloses:

%d signed integer
%h unsigned hexdecimal integer
%c character
%s string
\n newline 

;DECLARE VOID printf(CHARPTR string,...)
 prints data to vdu:
 (the ... arguments are values)

;DECLARE VOID fprintf(INT filehandle,CHARPTR string,...)
 prints data to filehandle
 (the ... arguments are values)

;DECLARE VOID inputf(CHARPTR string,...)
 prints character constants to vdu: and scan variables from keyboard
 (the ... arguments are adresses)

;DECLARE VOID finputf(INT filehandle,CHARPTR string,...)
 scans for data from a filehandle selected by whitespaces
 \n means: read till the end of the current line.
 (the ... arguments are adresses)

;DECLARE VOID field(INT fieldnr,CHARPTR target,CHARPTR source)
 copies fieldnr. th field (substring surrended by whitespaces) of source to
 target 

the rest are some functions useful for wimppolling.


Appendix D: Building full macro-assembler macros  
================================================

 If you want to avoid spending some resources for the generated macro-header, 
 (e.g. you want to implement a new often used library-macro in assembler)
 you can do the same on foot (instead using ;MACRO):

 macros are called in the form: 
 
  macro_name result,arg1,arg2,...argN

    (the following is for TLA)
    Write a Macro-header in the form: 
    .MACRO macro_name 
     insert here your code, (1. Argument is represented by %1, 2. by %2, ...
     N. by %N)
    .ENDM
    1. Argument belongs to the result-register, 2. Argument belongs to
    stackoffset of arg1 3. Argument belongs to stackoffset of arg2,...,
    N+1. argument belongs to stackoffset of argN.
    ***********************************************************************
    The arguments (except the first, which is a register) are STACKOFFSETS
    ***********************************************************************
;FUNCTION return its values via R0 to the first argument in the macrocall
;MACRO    return its values        to the first argument in the macrocall
    so use in the macrobody for arg(n) 
    [Stackregister(default R12),#arg(n)]
    Don't forget to let formula know the type of result and arguments with:  
       ;DECLARE type macro_name(type1,type2,...typeN) 
    type is type of result and type1...typeN is type of arg1...argN 
 
  ;DECLARE type macro_name(type1,type2,...typeN) 
 
 ;DECLARE also useful for include-files, if the macro itself is in a other
 part of the program. (e.g. the !formula.function_h file, which represent the
 macros come in !formula.functions)


Appendix E: How the stack looks in a function/macro
===================================================


name:               discription:                    length:

______________________________________________________________________________

oldregistersave-    registers which need to be      depents how much 
block               saved before functioncall       registers need to be saved
                                                    (4 Bytes each)
______________________________________________________________________________

argumentblock       arguments with which the        depends how much arguments
                    functions is called             needed 
                                                    (length of each depends on 
                                                    type (aligned to 4)) 
______________________________________________________________________________
------------------------------------------------------------------------------
<---- stackregister
------------------------------------------------------------------------------
tempregister-       place for a copy of             4 Bytes
copy                tempregister 
                    (saveregister/restoreregister)
______________________________________________________________________________

stackregister-      place for a copy of             4 Bytes
copy                stackregister 
                    (saveregister/restoreregister)
______________________________________________________________________________

flagscopy           place for a copy of             4 Bytes
                    flags 
                    (saveregister/restoreregister)
______________________________________________________________________________

returnadress        place for the returnadress      4 Bytes
                    of the function
                    (if needed)
______________________________________________________________________________

linkedlistpointer   place for a pointer to a linked 4 Bytes
                    list with adressed of alloced
                    memory for local arrays and 
                    structs (if needed)
_____________________________________________________________________________

localdatablock      block of local data             depends on local data
_____________________________________________________________________________

tempdatablock       block of temporary data         depends on temporary data
_____________________________________________________________________________


;FUNCTION return its values via R0 to the first argument in the macrocall
;MACRO    return its values        to the first argument in the macrocall
